/*
*    Qizx/open 3.0 beta
*
* This code is the open-source version of Qizx.
* Copyright (C) 2004-2009 Axyana Software -- All rights reserved.
*
* The contents of this file are subject to the Mozilla Public License 
*  Version 1.1 (the "License"); you may not use this file except in 
*  compliance with the License. You may obtain a copy of the License at
*  http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
*  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
*  for the specific language governing rights and limitations under the
*  License.
*
* The Initial Developer of the Original Code is Xavier Franc - Axyana Software.
*
*/
using System;
using EvaluationException = System.Qizx.Api.EvaluationException;
using ItemType = System.Qizx.Api.ItemType;
using Expression = System.Qizx.XQuery.Op.Expression;
namespace System.Qizx.XQuery
{
	
	/// <summary> Implementation of a Sequence Type with its occurrence indicator.</summary>
	public class SequenceType:XQType, System.Qizx.Api.ISequenceType
	{
		public override ItemType ItemType
		{
			get
			{
				return itemType_Renamed_Field;
			}
			
		}
		public override int Occurrence
		{
			get
			{
				return occ;
			}
			
		}
		private XQItemType itemType_Renamed_Field;
		
		private int occ = System.Qizx.Api.SequenceState.OCC_ZERO_OR_MORE;
		
		public SequenceType(XQItemType itemType)
		{
			this.itemType_Renamed_Field = itemType;
		}
		
		public SequenceType(XQItemType itemType, int occ)
		{
			this.itemType_Renamed_Field = itemType;
			this.occ = occ;
		}
		
		public override XQItemType itemType()
		{
			return itemType_Renamed_Field;
		}
		
		public override bool isOptional()
		{
			return isOptional(occ);
		}
		
		public override bool isRepeatable()
		{
			return isRepeatable(occ);
		}
		
		public override string toString(BasicStaticContext ctx)
		{
			string s = itemType_Renamed_Field.toString(ctx);
			switch (occ)
			{
				
				case System.Qizx.Api.SequenceState.OCC_ZERO_OR_ONE: 
					return s + "?";
				
				case System.Qizx.Api.SequenceState.OCC_ONE_OR_MORE: 
					return s + "+";
				
				case System.Qizx.Api.SequenceState.OCC_ZERO_OR_MORE: 
					return s + "*";
				
				default: 
					return s;
				
			}
		}
		
		public override string ToString()
		{
			string s = itemType_Renamed_Field.ToString();
			switch (occ)
			{
				
				case System.Qizx.Api.SequenceState.OCC_ZERO_OR_ONE: 
					return s + "?";
				
				case System.Qizx.Api.SequenceState.OCC_ONE_OR_MORE: 
					return s + "+";
				
				case System.Qizx.Api.SequenceState.OCC_ZERO_OR_MORE: 
					return s + "*";
				
				default: 
					return s;
				
			}
		}
		
		
		public override bool acceptsItem(XQItem item)
		{
			return itemType_Renamed_Field.acceptsItem(item); // occ one is always ok
		}
		
		public override bool accepts(XQType valueType)
		{
			XQItemType vitemType = valueType.itemType();
			if (vitemType == XQType.NONE)
				return isOptional(valueType.Occurrence);
			
			// That's all: we cannot check the occurrence count in static analysis
			return itemType_Renamed_Field.accepts(vitemType);
		}
		
		public override XQValue convertFromObject(System.Object object_Renamed)
		{
			if (!isRepeatable(occ))
			{
				return itemType_Renamed_Field.convertFromObject(object_Renamed);
			}
			return itemType_Renamed_Field.convertFromArray(object_Renamed);
		}
		
		public override System.Object convertToObject(Expression expr, Focus focus, EvalContext context)
		{
			if (!isRepeatable(occ))
			{
				return itemType_Renamed_Field.convertToObject(expr, focus, context);
			}
			try
			{
				return itemType_Renamed_Field.convertToArray(expr.eval(focus, context));
			}
			catch (XQTypeException e)
			{
				context.error(expr, e);
				return null;
			}
		}
		
		public override ItemType GetSuperType()
		{
			return ItemType.GetSuperType(); // whatever
		}
		
		public override bool IsSubTypeOf(ItemType type)
		{
			return false; // does not make sense
		}
	}
}